import { createReducer } from 'reduxsauce'
import { REHYDRATE } from 'redux-persist/es/constants'
import {
  REGISTER,
  SAVE_PATIENT,
  SELECT_PATIENT,
  GET_MY_PATIENTS,
  GET_PATIENT_RELATIONSHIP,
  GET_MY_PATIENTS_AND_REGISTRATION_STATUS,
  CLEAR_SELECT_PATIENT,
  GET_PAIN_LOGS,
  GET_PATIENT_BY_ID,
  GET_LATEST_PAIN_LOG,
  CREATE_PAIN_LOG,
  SET_PAIN_LOCATION,
  GET_PAIN_LOG_OPTIONS,
  SET_PAIN_LOG_SELECT_OPTION,
  CLEAR_PAIN_LOG_SELECT_OPTION,
  SET_PAIN_LOG_PATIENT,
  SET_PAIN_HEAD_SITE,
  GET_PAINLOG_HEAD_MAP,
  INIT_PAIN_DATA,
  SET_PAIN_FREQUENCY,
  SET_PAIN_TOTAL_TIME_MINUTE,
  GET_MY_CONSULTATIONS,
  SYNC_MY_CONSULTATIONS_UNREAD,
  GET_RELATED_TAGS_BY_NAME,
  SET_CURRENT_HISTORY_OPTIONS,
  GET_DEFAULT_PATIENT,
  SET_EXTRA_SITES,
  CHANGE_SHOW_OPTIONS,
  SET_CONSULTATION_REPORT_COUNT,
  SET_BODY_SITE,
  SHOW_CREATE_LOG,
} from '@ACTIONS/patient'
import {
  LOGOUT_USER,
} from '@ACTIONS/auth'
import { PAIN_OPTIONS_TYPE_MAP } from '@CONSTANTS/pain'

const INITIAL_STATE = {
  submitLoading: false,
  myPatients: [],
  selectedPatient: null,
  loadingMyPatientsAndStatus: false,
  myPatientsAndRegistrationStatus: [],
  canContactDocPatientList: [],
  relation: null,
  myPatientsLoading: false,
  error: null,
  painLogs: [],
  canLoadMorePainLogs: false,
  loadingPainLogs: false,
  formatPainLogs: {},
  patientDetail: {},
  loadingPatientDetail: true,
  loadingPatientDetailErrorMsg: '',
  loadingLogOptions: true,
  painLocations: [],
  painHeadSites: [],
  extraSites: [],
  painOverallLevel: 1,
  activityLevel: [],
  sessions: [],
  painActivityLevel: undefined,
  painConcomitantSymptom: [],
  painTriggers: [],
  painFrequency: 1,
  painTotalTimeMinute: 0.5,
  painRelief: [],
  painTreatments: [],
  painSymptoms: [],
  painAuras: [],
  painMedications: [],
  painMood: [],
  painSleep: undefined,
  painOther: undefined,
  painSessions: [],
  headMap: null,
  bodyMap: null,
  symptoms: null,
  auras: null,
  concomitantSymptom: null,
  triggers: null,
  relief: null,
  treatments: null,
  defaultMedicine: null,
  mood: null,
  sleep: null,
  latestPainLog: null,
  reliefText: '',
  triggerText: '',
  treatmentText: '',
  symptomText: '',
  AuraText: '',
  concomitantSymptomText: '',
  moodText: '',
  painLogPatient: null,
  // source: null,
  showOptions: false,
  myConsultationsWithTotal: {},
  currentHistoryTags: [],
  diagnosis: [],
  selectedCurrentHistoryTags: [],
  defaultPatient: {},
  unViewedCount: 0,
  importTime: 0,
  showCreateLog: false,
}

const OTHER_REASON_TEXT_MAP = {
  [PAIN_OPTIONS_TYPE_MAP.Relief]: 'reliefText',
  [PAIN_OPTIONS_TYPE_MAP.Triggers]: 'triggerText',
  [PAIN_OPTIONS_TYPE_MAP.ConcomitantSymptom]: 'concomitantSymptomText',
  [PAIN_OPTIONS_TYPE_MAP.Treatments]: 'treatmentText',
  [PAIN_OPTIONS_TYPE_MAP.Symptoms]: 'symptomText',
  [PAIN_OPTIONS_TYPE_MAP.Auras]: 'auraText',
  [PAIN_OPTIONS_TYPE_MAP.Mood]: 'moodText',
}

const getSiteType = data => (Array.isArray(data) ? data.map(item => item.BodyMap || item.HeadMap) : [])

const syncPatients = (patients = [], insertPatient, insertId, isEdit) => {
  const newPatients = isEdit
    ? patients?.map(item => (item.p8Id === insertId ? {
      ...insertPatient,
      p8Id: insertId
    } : item))
    : [...patients, {
      ...insertPatient,
      p8Id: insertPatient.p8Id || insertPatient.PatientId
    }]
  return newPatients
}

const removeInvalidData = (target, source) => {
  if (!Array.isArray(target)) {
    const isValid = source[target]
    return isValid ? target : ''
  }
  return target?.filter(item => source[item])
}

const rehydrate = (state, { payload }) => {
  if (payload && payload.patient) {
    return { ...INITIAL_STATE, ...payload.patient }
  }
  return { ...state }
}

export default createReducer(INITIAL_STATE, {
  [REHYDRATE]: rehydrate,
  [REGISTER.SUCCESS]: (state, { pId, status }) => ({
    ...state,
    myPatientsAndRegistrationStatus: state.myPatientsAndRegistrationStatus.map(item => (
      pId === item.PatientId ? {
        ...item,
        RegistrationStatus: status
      } : item
    )),
  }),
  [SAVE_PATIENT.REQUEST]: state => ({
    ...state,
    submitLoading: true,
  }),
  [SAVE_PATIENT.SUCCESS]: (state, { result, isEdit }) => {
    const editId = result?.PatientId
    const mypatients = syncPatients(state.myPatients, result, editId, isEdit)
    const myPatientsAndRegistrationStatus = syncPatients(state.myPatientsAndRegistrationStatus, result, editId, isEdit)
    return ({
      ...state,
      submitLoading: false,
      myPatientsAndRegistrationStatus,
      myPatients: mypatients,
      patientDetail: result
    })
  },
  [SAVE_PATIENT.FAILURE]: (state, { error }) => ({
    ...state,
    error,
    submitLoading: false,
  }),
  [GET_MY_PATIENTS.REQUEST]: state => ({
    ...state,
    myPatientsLoading: true
  }),
  [GET_MY_PATIENTS.FAILURE]: (state, { error }) => ({
    ...state,
    myPatientsLoading: false,
    error
  }),
  [GET_MY_PATIENTS.SUCCESS]: (state, { result }) => ({
    ...state,
    myPatients: result,
    myPatientsLoading: false
  }),
  [GET_PATIENT_RELATIONSHIP.SUCCESS]: (state, { relation, source }) => ({
    ...state,
    relation,
    source,
  }),
  [GET_MY_PATIENTS_AND_REGISTRATION_STATUS.REQUEST]: state => ({
    ...state,
    loadingMyPatientsAndStatus: true
  }),
  [GET_MY_PATIENTS_AND_REGISTRATION_STATUS.SUCCESS]: (state, { result, canContactDocPatientList }) => ({
    ...state,
    myPatientsAndRegistrationStatus: result,
    loadingMyPatientsAndStatus: false,
    canContactDocPatientList
  }),
  [GET_MY_PATIENTS_AND_REGISTRATION_STATUS.FAILURE]: (state, { error }) => ({
    ...state,
    loadingMyPatientsAndStatus: false,
    error
  }),
  [SELECT_PATIENT.REQUEST]: (state, { selectedPatient }) => ({
    ...state,
    selectedPatient,
  }),
  [CLEAR_SELECT_PATIENT.REQUEST]: state => ({
    ...state,
    selectedPatient: null,
  }),

  [GET_PAIN_LOGS.REQUEST]: (state, { payload: { skip } }) => ({
    ...state,
    loadingPainLogs: true,
    formatPainLogs: skip === 0 ? {} : state.formatPainLogs,
    painLogs: skip === 0 ? [] : state.painLogs
  }),
  [GET_PAIN_LOGS.SUCCESS]: (state, { painLogs, canLoadMore, formatPainLogs }) => ({
    ...state,
    painLogs,
    formatPainLogs,
    canLoadMorePainLogs: canLoadMore,
    loadingPainLogs: false,
  }),
  [GET_PAIN_LOGS.FAILURE]: (state, { error }) => ({
    ...state,
    error,
    loadingPainLogs: false,
  }),

  [GET_PATIENT_BY_ID.REQUEST]: state => ({
    ...state,
    loadingPatientDetail: true,
    loadingPatientDetailErrorMsg: '',
    patientDetail: {}
  }),
  [GET_PATIENT_BY_ID.SUCCESS]: (state, { data }) => ({
    ...state,
    loadingPatientDetail: false,
    loadingPatientDetailErrorMsg: '',
    patientDetail: data
  }),
  [GET_PATIENT_BY_ID.FAILURE]: (state, { error }) => ({
    ...state,
    loadingPatientDetailErrorMsg: error,
    loadingPatientDetail: false
  }),
  [CREATE_PAIN_LOG.FAILURE]: (state, { error }) => ({
    ...state,
    error,
  }),
  [SET_PAIN_LOCATION.SUCCESS]: (state, { result }) => ({
    ...state,
    painLocations: result,
  }),
  [SET_PAIN_LOCATION.FAILURE]: (state, { error }) => ({
    ...state,
    error,
  }),
  [SET_PAIN_HEAD_SITE.SUCCESS]: (state, { result }) => ({
    ...state,
    painHeadSites: result,
  }),
  [SET_PAIN_HEAD_SITE.FAILURE]: (state, { error }) => ({
    ...state,
    error,
  }),
  [GET_LATEST_PAIN_LOG.REQUEST]: (state, { payload }) => ({
    ...state,
    loadingLogOptions: !!payload?.loadOptions,
    showOptions: false,
    importTime: 0,
  }),
  [GET_LATEST_PAIN_LOG.SUCCESS]: (state, { result }) => ({
    ...state,
    latestPainLog: result,
    painLocations: [],
    painHeadSites: [],
    extraSites: [],
  }),
  [GET_LATEST_PAIN_LOG.FAILURE]: (state, { error }) => ({
    ...state,
    error,
    latestPainLog: null,
  }),
  [GET_PAIN_LOG_OPTIONS.SUCCESS]: (state, {
    bodyMap, symptoms, auras, concomitantSymptom, triggers, relief, treatments, defaultMedicine, mood, sleep, headMap, activityLevel, sessions
  }) => ({
    ...state,
    loadingLogOptions: false,
    bodyMap,
    symptoms,
    auras,
    concomitantSymptom,
    triggers,
    relief,
    treatments,
    defaultMedicine,
    mood,
    sleep,
    headMap,
    activityLevel,
    sessions
  }),
  [GET_PAIN_LOG_OPTIONS.FAILURE]: (state, { error }) => ({
    ...state,
    loadingLogOptions: false,
    error,
  }),
  [GET_PAIN_LOG_OPTIONS.REQUEST]: state => ({
    ...state,
    loadingLogOptions: true,
  }),
  [SET_PAIN_LOG_SELECT_OPTION.SUCCESS]: (state, {
    painOverallLevel, painActivityLevel, painConcomitantSymptom, painTriggers, painRelief, painTreatments,
    painMedications, painMood, painSleep, painOther, painType, otherReason, isOther, painSymptoms, painAuras, painSessions
  }) => ({
    ...state,
    painOverallLevel: painOverallLevel > -1 ? painOverallLevel : state.painOverallLevel,
    painActivityLevel: painActivityLevel ?? state.painActivityLevel,
    painConcomitantSymptom: painConcomitantSymptom || state.painConcomitantSymptom,
    painTriggers: painTriggers || state.painTriggers,
    painRelief: painRelief || state.painRelief,
    painTreatments: painTreatments || state.painTreatments,
    painSymptoms: painSymptoms || state.painSymptoms,
    painAuras: painAuras || state.painAuras,
    painMedications: painMedications || state.painMedications,
    painMood: painMood || state.painMood,
    painSleep: painSleep ?? state.painSleep,
    painOther: painOther ?? state.painOther,
    painSessions: painSessions ?? state.painSessions,
    [OTHER_REASON_TEXT_MAP[PAIN_OPTIONS_TYPE_MAP[painType]]]:
        isOther ? otherReason || '' : state[OTHER_REASON_TEXT_MAP[PAIN_OPTIONS_TYPE_MAP[painType]]],
  }),
  [CLEAR_PAIN_LOG_SELECT_OPTION.REQUEST]: state => ({
    ...state,
    painLocations: [],
    painHeadSites: [],
    painOverallLevel: 1,
    painActivityLevel: undefined,
    painConcomitantSymptom: [],
    painTriggers: [],
    painFrequency: 1,
    painTotalTimeMinute: 30,
    painRelief: [],
    painTreatments: [],
    painSymptoms: [],
    painAuras: [],
    painMedications: [],
    painMood: [],
    painSleep: undefined,
    painOther: undefined,
    painSessions: [],
    reliefText: '',
    concomitantSymptomText: '',
    triggerText: '',
    treatmentText: '',
    moodText: '',
    symptomText: '',
    auraText: '',
  }),
  [SET_PAIN_LOG_PATIENT.REQUEST]: (state, { result }) => ({
    ...state,
    painLogPatient: result,
  }),
  [GET_PAINLOG_HEAD_MAP.SUCCESS]: (state, { headMap }) => ({
    ...state,
    headMap
  }),
  [GET_PAINLOG_HEAD_MAP.FAILURE]: (state, { error }) => ({
    ...state,
    error
  }),
  [INIT_PAIN_DATA.SUCCESS]: (state, { options, result }) => {
    const { latestPainLog } = state
    const {
      ConcomitantSymptomKey, TriggersKey, OverallRating, ActivityLevel,
      Frequency, TotalTimeMinute, ReliefKey, TreatmentsKey, Medications, MoodKey, SleepKey, Notes,
      ReliefText, ConcomitantSymptomText, TriggerText, TreatmentText, MoodText, SymptomsKey, SymptomText,
      AurasKey, AuraText, BodyMaps, HeadMaps, SessionsKeys
    } = result || latestPainLog || {}
    const logOption = options || state
    const painSymptoms = removeInvalidData(SymptomsKey || [], logOption.symptoms)
    const painAuras = removeInvalidData(AurasKey || [], logOption.auras)
    const painTriggers = removeInvalidData(TriggersKey || [], logOption.triggers)
    const painConcomitantSymptom = removeInvalidData(ConcomitantSymptomKey || [], logOption.concomitantSymptom)
    const painRelief = removeInvalidData(ReliefKey || [], logOption.relief)
    const painMood = removeInvalidData(MoodKey || [], logOption.mood)
    const painTreatments = removeInvalidData(TreatmentsKey || [], logOption.treatments)
    const showOptions = ActivityLevel || !!painAuras?.length || !!painConcomitantSymptom?.length || !!painRelief?.length || !!painTreatments?.length
      || !!painMood?.length || !!SleepKey?.lessssngth || !!Notes?.length
    const hasAllData = BodyMaps?.length > 0 && HeadMaps?.length > 0
    const painSessions = removeInvalidData(SessionsKeys || [], logOption.sessions)
    return ({
      ...state,
      painLocations: getSiteType(hasAllData ? [] : BodyMaps),
      painHeadSites: getSiteType(hasAllData ? [] : HeadMaps),
      painOverallLevel: OverallRating?.Rating || 1,
      painActivityLevel: logOption.activityLevel?.[ActivityLevel?.Rating] ? ActivityLevel?.Rating : undefined,
      painConcomitantSymptom,
      painTriggers,
      painFrequency: Frequency || 1,
      painTotalTimeMinute: TotalTimeMinute || 30,
      painRelief,
      painTreatments,
      painSymptoms,
      painAuras,
      painMedications: Medications?.map(item => ({
        ...item.Name,
        id: item.MedicineId
      })) || [],
      painMood,
      painSleep: SleepKey || undefined,
      painOther: Notes || undefined,
      painSessions,
      reliefText: ReliefText || '',
      concomitantSymptomText: ConcomitantSymptomText || '',
      triggerText: TriggerText || '',
      treatmentText: TreatmentText || '',
      symptomText: SymptomText || '',
      auraText: AuraText || '',
      moodText: MoodText || '',
      importTime: Date.now(),
      extraSites: [],
      showOptions,
    })
  },
  [INIT_PAIN_DATA.FAILURE]: (state, { error }) => ({
    ...state,
    error
  }),
  [SET_PAIN_FREQUENCY.REQUEST]: (state, { count }) => ({
    ...state,
    painFrequency: count,
  }),
  [SET_PAIN_TOTAL_TIME_MINUTE.REQUEST]: (state, { time }) => ({
    ...state,
    painTotalTimeMinute: time,
  }),
  [GET_MY_CONSULTATIONS.SUCCESS]: (state, { myConsultationsWithTotal }) => ({
    ...state,
    myConsultationsWithTotal
  }),
  [GET_MY_CONSULTATIONS.FAILURE]: (state, { error }) => ({
    ...state,
    error
  }),

  [SYNC_MY_CONSULTATIONS_UNREAD]: (state, { consultationId }) => {
    const { myConsultationsWithTotal, myConsultationsWithTotal: { Consultations } } = state
    const consultations = Array.isArray(Consultations)
      && Consultations.map(item => (item.p8Id === consultationId ? {
        ...item,
        UnReadMessagCount: 0
      } : item))
    return ({
      ...state,
      myConsultationsWithTotal: {
        ...myConsultationsWithTotal,
        Consultations: consultations
      }
    })
  },

  [GET_RELATED_TAGS_BY_NAME.REQUEST]: state => ({
    ...state,
    selectedCurrentHistoryTags: [],
  }),
  [GET_RELATED_TAGS_BY_NAME.SUCCESS]: (state, { currentHistoryTags, diagnosis }) => ({
    ...state,
    currentHistoryTags,
    diagnosis,
  }),

  [SET_CURRENT_HISTORY_OPTIONS.SUCCESS]: (state, { selectedCurrentHistoryTags }) => ({
    ...state,
    selectedCurrentHistoryTags,
  }),

  [GET_DEFAULT_PATIENT.SUCCESS]: (state, { defaultPatient }) => ({
    ...state,
    defaultPatient,
    selectedPatient: state.myPatients?.length === 1 ? defaultPatient : state.selectedPatient
  }),
  [SET_EXTRA_SITES.REQUEST]: (state, { site }) => ({
    ...state,
    extraSites: state.extraSites.includes(site) ? state.extraSites.filter(i => i !== site) : [...state.extraSites, site],
  }),
  [CHANGE_SHOW_OPTIONS.REQUEST]: state => ({
    ...state,
    showOptions: !state.showOptions,
  }),
  [SET_CONSULTATION_REPORT_COUNT.REQUEST]: (state, { unViewedCount }) => ({
    ...state,
    unViewedCount,
  }),
  [SET_BODY_SITE.SUCCESS]: (state, { data }) => {
    const { painLocations, painHeadSites } = data || {}
    const isHead = painHeadSites?.length > 0
    const site = isHead ? { painLocations: [], painHeadSites } : { painLocations, painHeadSites: [] }
    return ({
      ...state,
      ...site,
      extraSites: [],
    })
  },
  [SHOW_CREATE_LOG.SUCCESS]: (state, { payload }) => ({
    ...state,
    ...payload
  }),

  [LOGOUT_USER.SUCCESS]: () => INITIAL_STATE,
})
